﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Configuration;

namespace MindmeisterAPI
{
    public class MindmeisterApi
    {
        public string APIKey { get; private set; }
        public string APISecret { get; private set; }

        public string APiFrob { get; set; }
        public string APiToken { get; set; }

        private const string API_Endpoint = "https://www.mindmeister.com/services/rest/";

        public MindmeisterApi(string pApiKey, string pApiSecret)
        {
            APIKey = pApiKey;
            APISecret = pApiSecret;
            if (ConfigurationManager.AppSettings["mmAPI_Token"] != "")
                APiToken = ConfigurationManager.AppSettings["mmAPI_Token"];
        }

        public string AuthenticateApplication(string pPerms)
        {
            Request r = new Request(APIKey, "mm.auth.getFrob");
            r.AddParameter("api_sig", r.GetSignature(APISecret));
            XmlDocument res = RequestTools.ExecuteRequest(API_Endpoint, APIKey, r);

            string frob = res.GetElementsByTagName("frob").Item(0).FirstChild.Value;
            APiFrob = frob;

            r = new Request(APIKey, "mm.auth.getToken");
            r.AddParameter("perms", "read");
            r.AddParameter("frob", frob);
            r.AddParameter("api_sig", r.GetSignature(APISecret));

            //r.AddParameter("perms", "read");
            //r.

            Dictionary<string, string> p = new Dictionary<string, string>();
            p.Add("api_key", APIKey);
            p.Add("frob", APiFrob);
            p.Add("perms", pPerms);

            return string.Format("http://www.mindmeister.com/services/auth/?api_key={0}&perms={1}&frob={2}&api_sig={3}", APIKey, pPerms, APiFrob, GenerateSignature(p, APISecret));
        }

        public string GetAuthToken()
        {
            Request r = new Request(APIKey, "mm.auth.getToken");

            r.AddParameter("frob", APiFrob);
            r.AddParameter("api_sig", r.GetSignature(APISecret));
            XmlDocument res = RequestTools.ExecuteRequest(API_Endpoint, APIKey, r);

            APiToken = res.GetElementsByTagName("token").Item(0).FirstChild.Value;
            ConfigurationManager.AppSettings["mmAPI_Token"] = APiToken;

            return APiToken;

        }

        public List<Map> GetMindmaps()
        {
            Request r = new Request(APIKey, "mm.maps.getList");

            r.AddParameter("auth_token", APiToken);
            r.AddParameter("api_sig", r.GetSignature(APISecret));
            XmlDocument res = RequestTools.ExecuteRequest(API_Endpoint, APIKey, r);

            List<Map> resultat = new List<Map>();

            foreach (XmlElement el in res.GetElementsByTagName("map"))
            {
                Map m = new Map(Convert.ToInt32(el.Attributes["id"].Value),
                                el.Attributes["title"].Value);
                resultat.Add(m);
            }


            return resultat;


        }

        public string GetMindmapPNGUrl(Map pMap)
        {
            Request r = new Request(APIKey, "mm.maps.export");

            r.AddParameter("auth_token", APiToken);
            r.AddParameter("map_id", pMap.Id.ToString());
            r.AddParameter("api_sig", r.GetSignature(APISecret));

            XmlDocument res = RequestTools.ExecuteRequest(API_Endpoint, APIKey, r);
            return res.GetElementsByTagName("image")[2].FirstChild.Value;
        }

        protected string GenerateSignature(Dictionary<string, string> pDictionnary, string pSharedKey)
        {
            StringBuilder res = new StringBuilder();
            res.Append(pSharedKey);

            foreach (KeyValuePair<string, string> item in pDictionnary.OrderBy(key => key.Key))
            {
                res.Append(item.Key);
                res.Append(item.Value);
            }
            return ComputeMD5(res.ToString());
        }


        private static string ComputeMD5(string pString)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] bs = System.Text.Encoding.UTF8.GetBytes(pString);
            bs = x.ComputeHash(bs);
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            foreach (byte b in bs)
            {
                s.Append(b.ToString("x2").ToLower());
            }
            return s.ToString();
        }
    }
}
